package com.inno.subject.domain.service.impl;

import com.inno.subject.domain.entity.SubjectRankBO;
import com.inno.subject.domain.service.SubjectRankDomainService;
import com.inno.subject.domain.utils.CacheUtil;
import com.inno.subject.domain.utils.CommonUtil;
import com.inno.subject.infra.basic.service.PlannerSubjectInfoService;
import com.inno.subject.infra.basic.service.PlannerSubjectRecordsService;
import com.inno.subject.infra.entity.RankCountBO;
import com.inno.subject.infra.entity.UserInfo;
import com.inno.subject.infra.rpc.UserRpc;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author sean
 */
@Service
@RequiredArgsConstructor
public class SubjectRankDomainServiceImpl implements SubjectRankDomainService {
    private final PlannerSubjectInfoService plannerSubjectInfoService;
    private final ThreadPoolTaskExecutor subjectExecutor;
    private final PlannerSubjectRecordsService plannerSubjectRecordsService;
    private final UserRpc userRpc;
    private final CacheUtil<SubjectRankBO> cacheUtil;

    @Override
    public List<SubjectRankBO> getRankInfo(SubjectRankBO subjectRankBO) {
        final String cacheKey = "subjectRank";
        return cacheUtil.get(cacheKey, SubjectRankBO.class,this::queryRank);
    }



    private List<SubjectRankBO> queryRank(SubjectRankBO subjectRankBO) {
        List<RankCountBO> rankCountBOS = plannerSubjectRecordsService.queryTotalCountGroupUserId();

        List<SubjectRankBO> subjectRankBOList = new ArrayList<>();
        for (RankCountBO rankCountBO : rankCountBOS) {
            SubjectRankBO bo = new SubjectRankBO();
            Long userId = rankCountBO.getUserId();
            Integer correctCount = rankCountBO.getCorrectCount();
            Integer totalRecord = rankCountBO.getTotalRecord();
            bo.setTotalRecord(totalRecord);
            bo.setCorrectRate(CommonUtil.calcRate(totalRecord, correctCount));
            bo.setUserId(userId);
            subjectRankBOList.add(bo);
        }
        // 正确率 总答题数量  userId 有了   还差 用户名 头像 性别 排名
        List<Long> userIdList = subjectRankBOList.stream().map(SubjectRankBO::getUserId).toList();
        List<UserInfo> userInfoList = userRpc.getUserInfoByIdList(userIdList);
        Map<Long, UserInfo> userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, Function.identity()));
        for (SubjectRankBO bo : subjectRankBOList) {
            UserInfo userInfo = userInfoMap.get(bo.getUserId());
            bo.setUsername(userInfo.getUsername());
            bo.setAvatar(userInfo.getAvatar());
        }
        // 差排名
        // 根据总答题数和正确率去计算排名   不能出现只做了一道题 正确率百分百 排第一这种情况
        subjectRankBOList.sort((bo1, bo2) -> {
            // 先比较总答题数
            int totalRecordCompare = bo2.getTotalRecord().compareTo(bo1.getTotalRecord());
            if (totalRecordCompare != 0) {
                return totalRecordCompare;
            }
            // 总答题数相同，比较正确率
            return bo2.getCorrectRate().compareTo(bo1.getCorrectRate());
        });
        // 计算排名
        for (int i = 0; i < subjectRankBOList.size(); i++) {
            SubjectRankBO bo = subjectRankBOList.get(i);
            bo.setRank(i + 1);
        }
        return subjectRankBOList;
    }
}
